/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package clusterAnalysis;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import units.CellType;
import units.DifferentialExpression;
import units.DifferentialExpressionLibrary;
import units.MonkeyType;
import utils.FileUtils;
import utils.Handle;
import utils.fishersExact.FishersExactTest;

/**
 *
 * @author jamie
 */
class ISGStats {

    private TreeMap<Integer, List<Integer>> geneMap;
    private List<Integer> isgs;
    private int popSize;
    private File outputFile = new File("/Users/jamie/Dropbox/monkeys/clust/stats/isgStats.txt");
    private BufferedWriter writer;
    private DifferentialExpressionLibrary del = new DifferentialExpressionLibrary();
    private double maxP = 0.1;
    private Integer[] timePoints = {1, 14, 28, 65};
    private double minRep = 2;

    public ISGStats(TreeMap<Integer, List<Integer>> geneMap) {
        writer = FileUtils.getBufferedWriter(outputFile);

        del.populateForAllMonkeyTypes(new units.GeneLibrary());
        this.geneMap = geneMap;

        for (CellType ct : CellType.values()) {
            for (MonkeyType mt : MonkeyType.values()) {
                for (int i = 1; i <= 15; i++) {
                    makeTest(i, mt, ct);
                }
            }
        }
        try {
            writer.close();
        } catch (IOException ex) {
            Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void makeTest(int clusterId, MonkeyType mt, CellType ct) {
        popSize = getPopSize(mt, ct);
        isgs = getISGs(mt, ct);
        TreeMap<Integer, List<DifferentialExpression>> differentialExpression = del.getDifferentialExpressedGenes(mt, ct, timePoints, maxP);
        System.out.println(differentialExpression.keySet().size() + " key set size");
        List<Integer> difExpGenes = getGeneIds(differentialExpression.keySet());
        List<Integer> geneIds = new ArrayList<Integer>();
        for (int gId : geneMap.get(clusterId)) {
            if (difExpGenes.contains(gId)) {
                geneIds.add(gId);
            }
        }
        if (geneIds.size() >= minRep) {
            List<Integer> intersect = new ArrayList<Integer>();

            intersect.addAll(isgs);
            intersect.retainAll(geneIds);
            if (intersect.size() > 0) {
                FishersExactTest fet = new FishersExactTest(popSize, isgs.size(), geneIds.size(), intersect.size());

                String out = clusterId + "\t" + mt.name() + "\t" + ct.name() + "\t" + popSize + "\t" + isgs.size() + "\t" + geneIds.size() + "\t" + intersect.size() + "\t" + fet.getFoldChange() + "\t" + fet.getResult();
                System.out.println(out);
                try {
                    writer.append(out + "\n");
                } catch (IOException ex) {
                    Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    private void makeTest(int clusterId) {
        List<Integer> geneIds = geneMap.get(clusterId);
        List<Integer> intersect = new ArrayList<Integer>();
        intersect.addAll(isgs);
        intersect.retainAll(geneIds);
        FishersExactTest fet = new FishersExactTest(popSize, isgs.size(), geneIds.size(), intersect.size());

        String out = clusterId + "\t" + popSize + "\t" + isgs.size() + "\t" + geneIds.size() + "\t" + intersect.size() + "\t" + fet.getFoldChange() + "\t" + fet.getResult();
        System.out.println(out);
        try {
            writer.append(out + "\n");
        } catch (IOException ex) {
            Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private List<Integer> getGeneIds(Collection<Integer> difExpProbeIds) {
        Handle handle = Handle.getConnectedHandle("monkeys");
        String sql;
        List<Integer> ids = new ArrayList<Integer>();
        for (int probeId : difExpProbeIds) {

            sql = "select distinct gId from probeIdlookup where probeId=" + probeId + "";
//            System.out.println(sql);
            ResultSet rs = handle.runSQLquery(sql);

            try {
                while (rs.next()) {
                    if (!ids.contains(rs.getInt("gId"))) {
                        ids.add(rs.getInt("gId"));
                    }
                }
                rs.close();
            } catch (SQLException ex) {
                Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        handle.closeConnection();
        return ids;
    }

    private List<Integer> getISGs(MonkeyType mt, CellType ct) {
        Handle handle = Handle.getConnectedHandle("monkeys");
        String sql;
        sql = "select distinct t1.gId from hcv.isgs t1, expression t2, sample t3 where t2.gId=t1.gId and t3.id=t2.sampleId and t3.monkeyType='" + mt.name() + "' and t3.cellType='" + ct.name() + "'";
        ResultSet rs = handle.runSQLquery(sql);
        List<Integer> ids = new ArrayList<Integer>();
        try {
            while (rs.next()) {
                ids.add(rs.getInt("gId"));
            }
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
        }
        handle.closeConnection();
        return ids;
    }

//    private int getPopSize() {
//        Handle handle = Handle.getConnectedHandle("monkeys");
//        String sql;
//        sql = "select count(distinct t1.gId) from probeidlookup t1, expression t2 where t1.probeId=t2.probeId";
//        ResultSet rs = handle.runSQLquery(sql);
//        int c = 0;
//        try {
//            if (rs.next()) {
//                c = rs.getInt("count(distinct t1.gId)");
//            }
//            rs.close();
//        } catch (SQLException ex) {
//            Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
//        }
//        handle.closeConnection();
//        return c;
//    }
    private int getPopSize(MonkeyType mt, CellType ct) {
        Handle handle = Handle.getConnectedHandle("monkeys");
        String sql;
        sql = "select count(distinct t2.gId) from expression t2, sample t3 where t3.id=t2.sampleId and t3.monkeyType='" + mt.name() + "' and t3.cellType='" + ct.name() + "'";
        System.out.println(sql);
        ResultSet rs = handle.runSQLquery(sql);
        int c = 0;
        try {
            if (rs.next()) {
                c = rs.getInt("count(distinct t2.gId)");
            }
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(ISGStats.class.getName()).log(Level.SEVERE, null, ex);
        }
        handle.closeConnection();
        return c;
    }
}
